#include<iostream>
#include<queue>

using namespace std;

typedef long long ll;
const int N=1e4+10;
int n,m;
int a[N],b[N],c[N];
struct cmz
{
	ll f;//函数值
	int num;//含函数编号
	int x;//带入值
	bool operator<(const cmz&x) const
	{
		return f>x.f;
	}
};
priority_queue<cmz> heap;

ll calc(int i,int x)
{
	return a[i]*x*x+b[i]*x+c[i];
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i]>>b[i]>>c[i];
	}
	//1把x=1值放入堆中
	for(int i=1;i<=n;i++)
	{
		heap.push({calc(i,1),i,1});
	}
	while(m--)
	{
		auto t=heap.top();heap.pop();
		ll f=t.f,num=t.num,x=t.x;
		cout<<f<<" ";
		heap.push({calc(num,x+1),num,x+1});
	}
	return 0;
}

// 由此可⻅，⼤可不必把所有的结果都算出来之后再放进去。可以先把所有函数代⼊ 1 的结果放进堆⾥
// ⾯。然后每次取出堆顶元素之后，就把堆顶元素对应函数的下⼀个结果算出来放进去。因为所有的函
// 数都是递增的，因此这种策略绝对是正确的。
// 由于取出堆顶元素之后要确定当前堆顶元素是谁，并且代⼊的数是多少。所以堆⾥⾯需要存⼀个结构
// 体，标注：函数值 + 哪个函数 + 代⼊的值，然后按照函数值创建⼩根堆即可